package org.javaboy.authentication_provider_kaptcha.config;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 校验验证码的 AuthenticationProvider
 * AuthenticationProvider 都是放在 AuthenticationManager 里边统一管理的，
 * DaoAuthenticationProvider 是专门去校验用户名密码的。
 * KaptchaAuthenticationProvider 则是专门去校验验证码的。
 * 将来两个要按顺序来，先执行 KaptchaAuthenticationProvider，后执行 DaoAuthenticationProvider
 */
public class KaptchaAuthenticationProvider extends DaoAuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //先做验证码校验
        //获取当前请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //这是用户输入的验证码
        String vcode = request.getParameter("vcode");
        //这是 session 中的验证码
        String kaptcha = (String) request.getSession().getAttribute("kaptcha");
        if (!vcode.equals(kaptcha)) {
            //说明验证码不对
            throw new RuntimeException("验证码错误");
        }
        //这就是调用父类的方法去进行用户名密码的校验
        return super.authenticate(authentication);
    }

    /**
     * 判断当前的登录操作是否需要被当前 AuthenticationProvider 处理
     *
     * 如果当前认证操作是用户名密码的方式，那么就通过这个 AuthenticationProvider 进行验证码的校验
     *
     * @param authentication
     * @return
     */
//    @Override
//    public boolean supports(Class<?> authentication) {
//        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
//    }
}
